package org.heng.service.Impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import lombok.RequiredArgsConstructor;
import org.heng.dao.entity.SeatDO;
import org.heng.dao.entity.TicketDO;
import org.heng.dao.mapper.SeatMapper;
import org.heng.dao.mapper.TicketMapper;
import org.heng.dto.SeatDetailsDTO;
import org.heng.dto.req.CancelSeatReqDTO;
import org.heng.dto.req.CreateSeatReqDTO;
import org.heng.dto.req.QueryAvaliableSeatReqDTO;
import org.heng.dto.resp.AvaliableSeatRespDTO;
import org.heng.service.SeatService;
import org.springframework.data.redis.connection.zset.Tuple;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class SeatServiceImpl extends ServiceImpl<SeatMapper, SeatDO>  implements SeatService {
    private final SeatMapper seatMapper;
    private final TicketMapper ticketMapper;
    private final StringRedisTemplate stringRedisTemplate;
    private static final String PREFIX_SEAT = "sob:seat:";
    @Override
    public AvaliableSeatRespDTO queryAvaliableSeat(QueryAvaliableSeatReqDTO requestParams) {
        stringRedisTemplate.opsForSet().pop("key", 10);
//        stringRedisTemplate.opsForZSet().pop
        List<String> list = stringRedisTemplate.opsForList().leftPop("ke", 100);
        String s = stringRedisTemplate.opsForList().leftPop("k", 1, TimeUnit.MINUTES);


        List<SeatDetailsDTO> seatDetailsDTOS = seatMapper.selectGroupedCount(requestParams.getName(), requestParams.getRegionList());
        if (seatDetailsDTOS.isEmpty()) {
            throw new RuntimeException("未找到演唱会门票信息");
        }
        AvaliableSeatRespDTO avaliableSeatRespDTO = new AvaliableSeatRespDTO();

        avaliableSeatRespDTO.setName(requestParams.getName());
        avaliableSeatRespDTO.setSeatDetailsDTOList(seatDetailsDTOS);
        long sum = seatDetailsDTOS.stream().mapToLong(SeatDetailsDTO::getCount).sum();

        avaliableSeatRespDTO.setAvaliableSeatCount(sum);
        return avaliableSeatRespDTO;
    }

    @Override
    public void createSeat(CreateSeatReqDTO requestParams) {
        Wrapper<TicketDO> queryWrapper = Wrappers.lambdaQuery(TicketDO.class)
                .eq(TicketDO::getName, requestParams.getName());
        TicketDO ticketDO = ticketMapper.selectOne(queryWrapper);
        if (ticketDO == null) {
            throw new RuntimeException("演唱会不存在");
        }
        try {
            List<SeatDO> seatDOList = new ArrayList<>();
            requestParams.getSeatDetailsDTOList().forEach(each -> {
                Set<Tuple> set = new HashSet<>();
                String cacheKey = PREFIX_SEAT + requestParams.getName() + each.getRegion();
                for (int i = 1; i <= each.getCount(); i++) {
                    SeatDO seatDO = new SeatDO();
                    seatDO.setCode(String.valueOf(i));
                    seatDO.setName(requestParams.getName());
                    seatDO.setRegion(each.getRegion());
                    seatDO.setPrice(each.getPrice());
                    seatDO.setStatus(0);
                    seatDO.setSId(ticketDO.getId());

                    set.add(Tuple.of(String.valueOf(i).getBytes(), (double) i));
                    seatDOList.add(seatDO);
                }
                stringRedisTemplate.executePipelined((RedisCallback<?>) connection -> {
                    connection.zSetCommands().zAdd(cacheKey.getBytes(), set);
                    return null;
                });
            });
            saveBatch(seatDOList);
        } catch (Exception e) {
            throw new RuntimeException("创建异常: " + e.getMessage());
        }
    }

    @Override
    public void cancelSeat(CancelSeatReqDTO requestParams) {
        seatMapper.cancelSeat(requestParams.getName(), requestParams.getRegion(), requestParams.getCodeList());
    }


}
